home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / os2 / mpegenc / src / bitio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  14.1 KB  |  546 lines

  1. /*===========================================================================*
  2.  * bitio.c                                     *
  3.  *                                         *
  4.  *    Procedures concerned with the bit-wise I/O                 *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    Bitio_New                                 *
  8.  *    Bitio_Free                                 *
  9.  *    Bitio_Write                                 *
  10.  *    Bitio_Flush                                 *
  11.  *    Bitio_WriteToSocket                             *
  12.  *    Bitio_BytePad                                 *
  13.  *                                         *
  14.  *===========================================================================*/
  15.  
  16. /*
  17.  * Copyright (c) 1993 The Regents of the University of California.
  18.  * All rights reserved.
  19.  *
  20.  * Permission to use, copy, modify, and distribute this software and its
  21.  * documentation for any purpose, without fee, and without written agreement is
  22.  * hereby granted, provided that the above copyright notice and the following
  23.  * two paragraphs appear in all copies of this software.
  24.  *
  25.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  26.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  27.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  28.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  31.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  32.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  33.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  34.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  35.  */
  36.  
  37. /*
  38.  *  $Header: /n/picasso/users/keving/encode/src/RCS/bitio.c,v 1.9 1993/07/22 22:23:43 keving Exp keving $
  39.  *  $Log: bitio.c,v $
  40.  * Revision 1.9  1993/07/22  22:23:43  keving
  41.  * nothing
  42.  *
  43.  * Revision 1.8  1993/06/30  20:06:09  keving
  44.  * nothing
  45.  *
  46.  * Revision 1.7  1993/06/03  21:08:08  keving
  47.  * nothing
  48.  *
  49.  * Revision 1.6  1993/02/17  23:21:41  dwallach
  50.  * checkin prior to keving's joining the project
  51.  *
  52.  * Revision 1.5  1993/01/18  10:20:02  dwallach
  53.  * *** empty log message ***
  54.  *
  55.  * Revision 1.4  1993/01/18  10:17:29  dwallach
  56.  * RCS headers installed, code indented uniformly
  57.  *
  58.  * Revision 1.4  1993/01/18  10:17:29  dwallach
  59.  * RCS headers installed, code indented uniformly
  60.  *
  61.  */
  62.  
  63. /*==============*
  64.  * HEADER FILES *
  65.  *==============*/
  66.  
  67. #include <assert.h>
  68. #include "all.h"
  69. #ifdef OS2
  70. /* @@@ FAT 8.3 convention */
  71. #include "byteorde.h"
  72. #else
  73. #include "byteorder.h"
  74. #endif
  75. #include "bitio.h"
  76. #include "mtypes.h"
  77.  
  78.  
  79. /*===============================*
  80.  * INTERNAL PROCEDURE prototypes *
  81.  *===============================*/
  82.  
  83. static void Dump _ANSI_ARGS_((BitBucket *bbPtr));
  84.  
  85.  
  86. /*==================*
  87.  * STATIC VARIABLES *
  88.  *==================*/
  89.  
  90. static uint32 lower_mask[33] = {
  91.     0,
  92.     0x1, 0x3, 0x7, 0xf,
  93.     0x1f, 0x3f, 0x7f, 0xff,
  94.     0x1ff, 0x3ff, 0x7ff, 0xfff,
  95.     0x1fff, 0x3fff, 0x7fff, 0xffff,
  96.     0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
  97.     0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
  98.     0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
  99.     0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
  100. };
  101.  
  102.  
  103. extern time_t IOtime;
  104.  
  105.  
  106. /*=====================*
  107.  * EXPORTED PROCEDURES *
  108.  *=====================*/
  109.  
  110.  
  111. /*===========================================================================*
  112.  *
  113.  * Bitio_New
  114.  *
  115.  *    Create a new bit bucket; filePtr is a pointer to the open file the
  116.  *    bits should ultimately be written to.
  117.  *
  118.  * RETURNS:    pointer to the resulting bit bucket
  119.  *
  120.  * SIDE EFFECTS:    none
  121.  *
  122.  *===========================================================================*/
  123. BitBucket *
  124. Bitio_New(filePtr)
  125.     FILE *filePtr;
  126. {
  127.     BitBucket *bbPtr;
  128.  
  129.     bbPtr = (BitBucket *) malloc(sizeof(BitBucket));
  130.     ERRCHK(bbPtr, "malloc");
  131.  
  132.     bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
  133.     ERRCHK(bbPtr->firstPtr, "malloc");
  134.  
  135.     bbPtr->totalbits = 0;
  136.     bbPtr->cumulativeBits = 0;
  137.     bbPtr->bitsWritten = 0;
  138.     bbPtr->filePtr = filePtr;
  139.  
  140.     bbPtr->firstPtr->nextPtr = NULL;
  141.     bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;
  142.     bbPtr->firstPtr->bitsleftcur = 32;
  143.     bbPtr->firstPtr->currword = 0;
  144.     bzero((char *)bbPtr->firstPtr->bits, sizeof(uint32) * WORDS_PER_BUCKET);
  145.  
  146.     return bbPtr;
  147. }
  148.  
  149.  
  150. /*===========================================================================*
  151.  *
  152.  * Bitio_Free
  153.  *
  154.  *    Frees the memory associated with the given bit bucket
  155.  *
  156.  * RETURNS:    nothing
  157.  *
  158.  * SIDE EFFECTS:    none
  159.  *
  160.  *===========================================================================*/
  161. void
  162. Bitio_Free(bbPtr)
  163.     BitBucket *bbPtr;
  164. {
  165.     struct bitBucket *tmpPtr, *nextPtr;
  166.  
  167.     for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {
  168.     nextPtr = tmpPtr->nextPtr;
  169.     free(tmpPtr);
  170.     }
  171.     free(bbPtr);
  172. }
  173.  
  174.  
  175. /*===========================================================================*
  176.  *
  177.  * Bitio_Write
  178.  *
  179.  *    Writes 'nbits' bits from 'bits' into the given bit bucket
  180.  *    'nbits' must be between 0 and 32
  181.  *
  182.  * RETURNS:    nothing
  183.  *
  184.  * SIDE EFFECTS:    if the number of bits in the bit bucket surpasses
  185.  *            MAX_BITS, then that many bits are flushed to the
  186.  *            appropriate output file
  187.  *
  188.  *===========================================================================*/
  189. void
  190. Bitio_Write(bbPtr, bits, nbits)
  191.     BitBucket *bbPtr;
  192.     uint32 bits;
  193.     int nbits;
  194. {
  195.     register struct bitBucket *lastPtr, *newPtr;
  196.     register int delta;
  197.  
  198.     assert(nbits <= 32 && nbits >= 0);
  199.  
  200.     /*
  201.      * Clear top bits if not part of data, necessary due to down and
  202.      * dirty calls of Bitio_Write with unecessary top bits set.
  203.      */
  204.  
  205.     bits = bits & lower_mask[nbits];
  206.  
  207.     bbPtr->totalbits += nbits;
  208.     bbPtr->cumulativeBits += nbits;
  209.     lastPtr = bbPtr->lastPtr;
  210.  
  211.     delta = nbits - lastPtr->bitsleft;
  212.     if (delta >= 0) {
  213.     /*
  214.          * there's not enough room in the current bucket, so we're
  215.          * going to have to allocate another bucket
  216.          */
  217.     newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
  218.     ERRCHK(newPtr, "malloc");
  219.     newPtr->nextPtr = NULL;
  220.     newPtr->bitsleft = MAXBITS_PER_BUCKET;
  221.     newPtr->bitsleftcur = 32;
  222.     newPtr->currword = 0;
  223.     bzero(newPtr->bits, sizeof(uint32) * WORDS_PER_BUCKET);
  224.     bbPtr->lastPtr = newPtr;
  225.  
  226.     assert(lastPtr->currword == WORDS_PER_BUCKET - 1);
  227.     lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);
  228.     lastPtr->bitsleft = 0;
  229.     lastPtr->bitsleftcur = 0;
  230.     /* lastPtr->currword++; */
  231.  
  232.     if (!delta) {
  233.         if ( bbPtr->totalbits > MAX_BITS ) {
  234.         Dump(bbPtr);
  235.         }
  236.     }
  237.  
  238.     assert(delta <= 32);
  239.     newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);
  240.     newPtr->bitsleft -= delta;
  241.     newPtr->bitsleftcur -= delta;
  242.     } else {
  243.     /*
  244.          * the current bucket will be sufficient
  245.      */
  246.     delta = nbits - lastPtr->bitsleftcur;
  247.     lastPtr->bitsleftcur -= nbits;
  248.     lastPtr->bitsleft -= nbits;
  249.  
  250.     if (delta >= 0)
  251.     {
  252.         /*
  253.          * these bits will span more than one word
  254.          */
  255.         lastPtr->bits[lastPtr->currword] |= (bits >> delta);
  256.         lastPtr->currword++;
  257.         lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);
  258.         lastPtr->bitsleftcur = 32 - delta;
  259.     } else {
  260.         /*
  261.          * these bits will fit, whole
  262.          */
  263.         lastPtr->bits[lastPtr->currword] |= (bits << (-delta));
  264.     }
  265.     }
  266.  
  267.     if ( bbPtr->totalbits > MAX_BITS )    /* flush bits */
  268.     Dump(bbPtr);
  269. }
  270.  
  271.  
  272. /*===========================================================================*
  273.  *
  274.  * Bitio_Flush
  275.  *
  276.  *    Flushes all of the remaining bits in the given bit bucket to the
  277.  *    appropriate output file.  It will generate up to the nearest 8-bit
  278.  *    unit of bits, which means that up to 7 extra 0 bits will be appended
  279.  *    to the end of the file.
  280.  *
  281.  * RETURNS:    nothing
  282.  *
  283.  * SIDE EFFECTS:    frees the bit bucket
  284.  *
  285.  *===========================================================================*/
  286. void
  287. Bitio_Flush(bbPtr)
  288.     BitBucket *bbPtr;
  289. {
  290.     struct bitBucket *ptr, *tempPtr;
  291.     uint32 buffer[WORDS_PER_BUCKET];
  292.     uint32  lastWord;
  293.     int i, nitems;
  294.     int        bitsWritten = 0;
  295.     int        bitsLeft;
  296.     int        numWords;
  297.     uint8   charBuf[4];
  298.     boolean    flushHere = FALSE;
  299.     time_t  tempTimeStart, tempTimeEnd;
  300.  
  301.     time(&tempTimeStart);
  302.  
  303.     bitsLeft = bbPtr->totalbits;
  304.  
  305.     for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
  306.     if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
  307.         continue;        /* empty */
  308.     }
  309.  
  310.     if ( bitsLeft >= 32 ) {
  311.         if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
  312.         numWords = ptr->currword;
  313.         flushHere = TRUE;
  314.         } else {
  315.         numWords = ptr->currword+1;
  316.         }
  317.  
  318.         for (i = 0; i < numWords; i++) {
  319.         buffer[i] = htonl(ptr->bits[i]);
  320.         }
  321.  
  322.         nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);
  323.         if (nitems != numWords) {
  324.         fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d items)!  Game over, dude!\n",
  325.             (int)(numWords), nitems);
  326.         exit(1);
  327.         }
  328.  
  329.         bitsWritten += (numWords * 32);
  330.         bitsLeft -= (numWords * 32);
  331.     } else {
  332.         flushHere = TRUE;
  333.     }
  334.  
  335.     if ( (bitsLeft < 32) && flushHere ) {
  336.         lastWord = ptr->bits[ptr->currword];
  337.  
  338.         /* output the lastPtr word in big-endian order (network) */
  339.  
  340.         /* now write out lastPtr bits */
  341.         while ( bitsLeft > 0 ) {
  342.         charBuf[0] = (lastWord >> 24);
  343.         charBuf[0] &= lower_mask[8];
  344.         fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);
  345.         lastWord = (lastWord << 8);
  346.         bitsLeft -= 8;
  347.         bitsWritten += 8;
  348.         }
  349.     }
  350.     }
  351.  
  352.     while ( bbPtr->firstPtr != ptr ) {
  353.     tempPtr = bbPtr->firstPtr;
  354.     bbPtr->firstPtr = tempPtr->nextPtr;
  355.     free(tempPtr);
  356.     }
  357.  
  358.     free(bbPtr);
  359.  
  360.     time(&tempTimeEnd);
  361.     IOtime += (tempTimeEnd-tempTimeStart);
  362. }
  363.  
  364.  
  365. /*===========================================================================*
  366.  *
  367.  * Bitio_WriteToSocket
  368.  *
  369.  *    Writes all of the remaining bits in the given bit bucket to the
  370.  *    given socket.  May pad the end of the socket stream with extra 0
  371.  *    bits as does Bitio_Flush.
  372.  *
  373.  * RETURNS:    nothing
  374.  *
  375.  * SIDE EFFECTS:    frees the bit bucket
  376.  *
  377.  *===========================================================================*/
  378. void
  379. Bitio_WriteToSocket(bbPtr, socket)
  380.     BitBucket *bbPtr;
  381.     int socket;
  382. {
  383. /* @@@ Socket stuff, ie: parallel compression not supported, Andy Key */
  384. #ifdef OS2
  385.     fprintf(stderr, "Socket stuff not supported under OS/2\n");
  386.     exit(1);
  387. #else
  388.     struct bitBucket *ptr, *tempPtr;
  389.     uint32 buffer[WORDS_PER_BUCKET];
  390.     uint32  lastWord;
  391.     int i, nitems;
  392.     int        bitsWritten = 0;
  393.     int        bitsLeft;
  394.     int        numWords;
  395.     uint8   charBuf[4];
  396.     boolean    flushHere = FALSE;
  397.  
  398.     bitsLeft = bbPtr->totalbits;
  399.  
  400.     for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
  401.     if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
  402.         continue;        /* empty */
  403.     }
  404.  
  405.     if ( bitsLeft >= 32 ) {
  406.         if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
  407.         numWords = ptr->currword;
  408.         flushHere = TRUE;
  409.         } else {
  410.         numWords = ptr->currword+1;
  411.         }
  412.  
  413.         for (i = 0; i < numWords; i++) {
  414.         buffer[i] = htonl(ptr->bits[i]);
  415.         }
  416.  
  417.         nitems = write(socket, buffer, numWords * sizeof(uint32));
  418.         if (nitems != numWords*sizeof(uint32)) {
  419.         fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d bytes)!  Game over, dude!\n",
  420.             (int)(numWords*sizeof(uint32)), nitems);
  421.         exit(1);
  422.         }
  423.  
  424.         bitsWritten += (numWords * 32);
  425.         bitsLeft -= (numWords * 32);
  426.     } else {
  427.         flushHere = TRUE;
  428.     }
  429.  
  430.     if ( (bitsLeft < 32) && flushHere ) {
  431.         lastWord = ptr->bits[ptr->currword];
  432.  
  433.         /* output the lastPtr word in big-endian order (network) */
  434.  
  435.         /* now write out lastPtr bits */
  436.         while ( bitsLeft > 0 ) {
  437.         charBuf[0] = (lastWord >> 24);
  438.         charBuf[0] &= lower_mask[8];
  439.         if ( write(socket, charBuf, 1) != 1 ) {
  440.             fprintf(stderr, "ERROR:  write of lastPtr bits\n");
  441.             exit(1);
  442.         }
  443.         lastWord = (lastWord << 8);
  444.         bitsLeft -= 8;
  445.         bitsWritten += 8;
  446.         }
  447.     }
  448.     }
  449.  
  450.     while ( bbPtr->firstPtr != ptr ) {
  451.     tempPtr = bbPtr->firstPtr;
  452.     bbPtr->firstPtr = tempPtr->nextPtr;
  453.     free(tempPtr);
  454.     }
  455.  
  456.     free(bbPtr);
  457. #endif
  458. }
  459.  
  460.  
  461. /*===========================================================================*
  462.  *
  463.  * Bitio_BytePad
  464.  *
  465.  *    Pads the end of the bit bucket to the nearest byte with 0 bits
  466.  *
  467.  * RETURNS:    nothing
  468.  *
  469.  *===========================================================================*/
  470. void
  471. Bitio_BytePad(bbPtr)
  472.     BitBucket *bbPtr;
  473. {
  474.     struct bitBucket *lastPtrPtr = bbPtr->lastPtr;
  475.  
  476.     if (lastPtrPtr->bitsleftcur % 8) {
  477.     Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);
  478.     }
  479. }
  480.  
  481.  
  482. /*=====================*
  483.  * INTERNAL PROCEDURES *
  484.  *=====================*/
  485.  
  486.  
  487. /*===========================================================================*
  488.  *
  489.  * Dump
  490.  *
  491.  *    Writes out the first MAX_BITS bits of the bit bucket to the
  492.  *    appropriate output file
  493.  *
  494.  * RETURNS:    nothing
  495.  *
  496.  * SIDE EFFECTS:  none
  497.  *
  498.  *===========================================================================*/
  499. static void
  500. Dump(bbPtr)
  501.     BitBucket *bbPtr;
  502. {
  503.     struct bitBucket *ptr, *tempPtr;
  504.     uint32 buffer[WORDS_PER_BUCKET];
  505.     int i, nitems;
  506.     int        bitsWritten = 0;
  507.     time_t  tempTimeStart, tempTimeEnd;
  508.  
  509.     time(&tempTimeStart);
  510.  
  511.     for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);
  512.      ptr = ptr->nextPtr) {
  513.     if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
  514.         continue;        /* empty */
  515.     }
  516.  
  517.     for (i = 0; i <= ptr->currword; i++) {
  518.         buffer[i] = htonl(ptr->bits[i]);
  519.     }
  520.  
  521.     nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr);
  522.     if (nitems != (ptr->currword+1)) {
  523.         fprintf(stderr, "Whoa!  Trouble writing %d bytes (got %d items)!  Game over, dude!\n",
  524.             (int)((ptr->currword+1)), nitems);
  525.         assert(0);
  526.         exit(1);
  527.     }
  528.  
  529.     bitsWritten += ((ptr->currword + 1) * 32);
  530.     }
  531.  
  532.     while ( bbPtr->firstPtr != ptr ) {
  533.     tempPtr = bbPtr->firstPtr;
  534.     bbPtr->firstPtr = tempPtr->nextPtr;
  535.     free(tempPtr);
  536.     }
  537.  
  538.     bbPtr->totalbits -= bitsWritten;
  539.     bbPtr->bitsWritten += bitsWritten;
  540.  
  541.     time(&tempTimeEnd);
  542.     IOtime += (tempTimeEnd-tempTimeStart);
  543. }
  544.  
  545.  
  546.